import numpy as np

from FluidClass.FluidSettings import FluidSettings
from ResistanceClass.ResistanceAbstractClass import ResistanceAbstractClass as RAC
from math import pi, log10, sin
from Utilities.MathFunctions import polynom

class CurveRectSmoothWallPipe(RAC):

    def __init__(self,
                 fluid: FluidSettings,
                 width: float,
                 height: float,
                 bend_radius: float,
                 bend_angle: float) -> None:
        super().__init__(fluid)
        self.width = width
        self.height = height
        self.bend_radius = bend_radius
        self.bend_angle = bend_angle
        self.type_name = 'Изогнутый участок'
        self.section = 'Прямоугольное'
        self.A_1, self.B_1, self.C_1 = None, None, None
        self.ratio_radius_to_height = round(self.bend_radius / self.height, 2)

    @staticmethod
    def trend_A1(x):
        return round(-4e-5 * x ** 2 + 0.0142 * x + 0.0356, 3)

    def area(self) -> float:
        return self.width * self.height

    def perimeter(self) -> float:
        return 2 * self.width + 2 * self.height

    def diameter_hydraulic(self) -> float:
        return round(4 * self.area() / self.perimeter(), 4)

    def definition_A_1(self):
        if self.bend_angle < 70:
            self.A_1 = round(0.9 * sin(self.bend_angle * pi / 180), 3)
        elif 70 <= self.bend_angle <= 100:
            self.A_1 = self.trend_A1(self.bend_angle)
        else:
            self.A_1 = round(0.7 + 0.35 * (self.bend_angle / 90), 3)
        return self.A_1

    def definition_B_1(self):
        if 0.5 <= self.ratio_radius_to_height <= 1:
            self.B_1 = round(0.21 * (self.ratio_radius_to_height ** (-2.5)), 2)
        elif self.ratio_radius_to_height > 1:
            self.B_1 = round(0.21 * (self.ratio_radius_to_height ** (-0.5)), 2)
        return self.B_1

    def definition_C_1(self):
        if self.width == self.height:
            self.C_1 = 1
        else:
            if 0 < self.ratio_radius_to_height <= 4:
                self.C_1 = round(0.85 + 0.125 / (self.width / self.height), 3)
            else:
                self.C_1 = round(1.115 - 0.84 / (self.width / self.height), 3)
        return self.C_1

    def local_resistance_coefficient(self) -> float:
        return self.definition_A_1() * self.definition_B_1() * self.definition_C_1()

    def resistance_coefficient_lambda(self) -> (str, float):
        if self.reynolds_number() < 2000:
            return 64 / self.reynolds_number()

        elif 2000 <= self.reynolds_number() <= 4000:
            re_database = [2, 2.5, 3, 4]
            lambda_database = [0.032, 0.034, 0.04, 0.04]
            re_database = np.array(re_database) * 10 ** 3
            return polynom(self.reynolds_number(), re_database, lambda_database, 4)

        elif self.reynolds_number() > 4000:
            return 1 / ((1.8 * log10(self.reynolds_number()) - 1.64) ** 2)

    def frictional_resistance_coefficient(self):
        return 0.0175 * self.bend_angle * self.resistance_coefficient_lambda() * self.ratio_radius_to_height

    def get_params_geom(self):
        self.params_geom['Радиус гиба'] = str(self.bend_radius) + ' м'
        self.params_geom['Угол гиба'] = str(self.bend_angle) + ' град'
        self.params_geom['Ширина'] = str(self.width) + ' м'
        self.params_geom['Высота'] = str(self.height) + ' м'
        return self.params_geom